package com.infra.server.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.infra.server.entity.SysResource;
import com.infra.server.entity.SysRole;
import com.infra.server.entity.SysRouter;
import com.infra.server.mapper.SysRoleMapper;
import com.infra.server.service.SysResourceService;
import com.infra.server.service.SysRoleService;
import com.infra.server.service.SysRouterService;
import com.infra.server.utils.ConstantUtil;
import com.infra.server.utils.RedisUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;


/**
 * @Author: gisocn
 * @Date: 2020/9/23
 * @Description: 角色服务实现类
 **/
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

    @Resource
    private SysRoleService sysRoleService;
    @Resource
    private SysResourceService sysResourceService;
    @Resource
    private SysRouterService sysRouterService;

    @Resource
    private RedisUtil redisUtil;

    @Override
    public List<SysRouter> getRouterByRoleIds(List<Integer> roleIds) {
        return this.baseMapper.getRouterByRoleIds(roleIds);
    }

    @Override
    public List<Object> getRouterByRoleId(Integer roleId) {
        return this.baseMapper.getRouterByRoleId(roleId);
    }

    /**
     * 需要开启事务，先删除旧的权限，再添加新权限
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int saveRoleRouter(Integer roleId, Object routerPermission) {
        if (ObjectUtil.isNotEmpty(routerPermission)) {
            this.baseMapper.delRoleRouterByRoleId(roleId);
            return this.baseMapper.saveRoleRouter(routerPermission);
        } else {
            return this.baseMapper.delRoleRouterByRoleId(roleId);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteRoleByRoleId(Integer roleId,String roleName) {
        // 删除角色资源
        QueryWrapper<SysResource> queryWrapper = new QueryWrapper<>();
        // 查询出包含此角色的资源
        queryWrapper.apply(roleName != null,"FIND_IN_SET ('"+ roleName +"', owner )");
        List<SysResource> sysResourceList = sysResourceService.list(queryWrapper);
        if (ObjectUtil.isNotEmpty(sysResourceList)) {
            List<SysResource> newSysResourceList = new ArrayList<>();
            for (SysResource s : sysResourceList) {
                String oldOwner = s.getOwner();
                List<String> list = new ArrayList<>(Arrays.asList(oldOwner.split(",")));
                list.remove(roleName);
                s.setOwner(String.join(",",list));
                newSysResourceList.add(s);
            }
            boolean a = sysResourceService.updateBatchById(newSysResourceList);
            if(a) {
                Map<String, Object> resourceMap = new HashMap<>();
                for (SysResource r : newSysResourceList) {
                    resourceMap.put(r.getName(),ObjectUtil.isNotEmpty(r.getOwner()) ? r.getOwner().split(",") : "");
                }
                // 保存到redis,已存在则会覆盖
                redisUtil.hmset(ConstantUtil.RESOURCE_ROLES_MAP, resourceMap);
            }
        }

        // 删除角色路由权限
        this.baseMapper.delRoleRouterByRoleId(roleId);
        // 删除角色用户
        this.baseMapper.delUserRole(roleId);
        return sysRoleService.removeById(roleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int savePermission(Map<String, Object> map) {
        int a = 0;
        Integer roleId = (Integer) map.get("roleId");
        Object routerPermission = map.get("routerPermission");
        Object resourcePermission = map.get("resourcePermission");
        Object userPermission = map.get("userPermission");

        // 路由权限
        a = a + saveRoleRouter(roleId,routerPermission);
        // 资源权限
        List<SysResource> resourceList = JSON.parseArray(JSON.toJSONString(resourcePermission), SysResource.class);;
        boolean b = sysResourceService.updateBatchById(resourceList);
        if(b) {
            Map<String, Object> resourceMap = new HashMap<>();
            for (SysResource r : resourceList) {
                if (StrUtil.isNotEmpty(r.getName()) && StrUtil.isNotEmpty(r.getOwner())) {
                    resourceMap.put(r.getName(),r.getOwner().split(","));
                } else {
                    redisUtil.hset(ConstantUtil.RESOURCE_ROLES_MAP,r.getName(),"");
                }
            }
            // 保存到redis,已存在则会覆盖
            if (ObjectUtil.isNotEmpty(resourceMap)) {
                redisUtil.hmset(ConstantUtil.RESOURCE_ROLES_MAP, resourceMap);
            }
            a = a + 1;
        }
        // 用户权限
        a = a + this.baseMapper.delUserRole(roleId);
        if (ObjectUtil.isNotEmpty(userPermission)) {
            a = a + this.baseMapper.addUserRole(userPermission);
        }
        return a;
    }

    @Override
    public List<Long> getUserByRoleId(Integer roleId) {
        return this.baseMapper.getUserByRoleId(roleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveDefaultPermission(Map<String, Object> map) {
        List<String> routerDefaultPermission = Convert.toList(String.class,map.get("routerDefaultPermission"));
        List<String> resourceDefaultPermission = Convert.toList(String.class,map.get("resourceDefaultPermission"));

        List<SysRouter> sysRouterList = sysRouterService.list();
        for (SysRouter s : sysRouterList) {
            if (routerDefaultPermission.contains(s.getId().toString())) {
                s.setRouterType(2);
            } else {
                s.setRouterType(1);
            }
        }

        List<SysResource> sysResourceList = sysResourceService.list(new LambdaQueryWrapper<SysResource>()
                .ne(SysResource::getResourceType,0));
        for (SysResource s : sysResourceList) {
            if (resourceDefaultPermission.contains(s.getId().toString())) {
                s.setResourceType(2);
            } else {
                s.setResourceType(1);
            }
        }

        sysRouterService.updateBatchById(sysRouterList);
        sysResourceService.updateBatchById(sysResourceList);
    }

}
